﻿using System;
using System.Linq;
using TaskManager.Domain.BusinessObjects;

namespace TaskManager.Domain.Repositories
{
    /// <summary>
    /// Users repository
    /// </summary>
    public interface IUserRepository
    {
        /// <summary>
        /// Searches for the user by name
        /// </summary>
        /// <param name="name">User name</param>
        /// <returns>Found user or null if user was not found</returns>
        User FindByName(string name);

        /// <summary>
        /// Searches for the user by identifier
        /// </summary>
        /// <param name="id">User identifier</param>
        /// <returns>Found user or null if user was not found</returns>
        User Find(int id);

        /// <summary>
        /// Returns all available users
        /// </summary>
        IQueryable<User> All { get; }

        /// <summary>
        /// Deletes user
        /// </summary>
        /// <param name="id">User identifier</param>
        /// <param name="commit">Lambda that will be invoked if user was successfully deleted in order to commit changes</param>
        /// <remarks>Since users are stored both in the application database and ASP.Net membership's database it is 
        /// recommended to commit changes in <c>commit</c> delegate</remarks>
        /// <example>
        /// userRepository.Delete(1, () => _unitOfWork.Save());
        /// </example>
        void Delete(int id, Action commit);

        /// <summary>
        /// Deletes user
        /// </summary>
        /// <param name="userName">User name</param>
        /// <param name="commit">Lambda that will be invoked if user was successfully deleted in order to commit changes</param>
        /// <remarks>Since users are stored both in the application database and ASP.Net membership's database it is 
        /// recommended to commit changes in <c>commit</c> delegate</remarks>
        /// <example>
        /// userRepository.Delete("user1", () => _unitOfWork.Save());
        /// </example>
        void Delete(string userName, Action commit);

        /// <summary>
        /// Verifies that the supplied user name and password are valid
        /// </summary>
        /// <param name="userName">User name</param>
        /// <param name="password">Password</param>
        /// <returns>true if the supplied user name and password are valid;false otherwise</returns>
        bool ValidateUser(string userName, string password);

        /// <summary>
        /// Creates a new user
        /// </summary>
        /// <param name="userName">User name</param>
        /// <param name="password">Password</param>
        /// <param name="email">Email</param>
        /// <param name="commit">Lambda that will be invoked if user was successfully created</param>
        /// <returns>Pair where the first element is <see cref="User"/> object, the second is error description</returns>
        /// <remarks>Since users are stored both in the application database and ASP.Net membership's database it is 
        /// recommended to commit changes in <c>commit</c> delegate</remarks>
        /// <example>
        /// userRepository.CreateUser("userName1", "password1", "email1", () => _unitOfWork.Save());
        /// </example>
        Tuple<User, string> CreateUser(string userName, string password, string email, Action commit);

        /// <summary>
        /// Changes password for the given user
        /// </summary>
        /// <param name="userName">User name</param>
        /// <param name="oldPassword">Old password</param>
        /// <param name="newPassword">New password</param>
        /// <returns>true if password was successfully changes; false otherwise</returns>
        bool ChangePassword(string userName, string oldPassword, string newPassword);
    }
}